package com.turtle3d.user.grammars;

import java.util.ArrayList;

import com.turtle3d.App;
import com.turtle3d.formallanguage.grammar.Grammar;
import com.turtle3d.formallanguage.grammar.Production;
import com.turtle3d.formallanguage.parser.SimpleParser;
import com.turtle3d.formallanguage.symbol.Condition;
import com.turtle3d.formallanguage.symbol.Method;
import com.turtle3d.formallanguage.symbol.Symbol;
import com.turtle3d.formallanguage.symbol.SymbolFactory;

public class RowOfTrees2D extends Grammar
{
	
	static float c=1;
	static float p=0.3f;
	static float q=c-p;
	static float h;
	
	public RowOfTrees2D(){
		h = (float)Math.sqrt((p*q));
	}

	@Override
	public void define()
	{
		
		setAxiom(SymbolFactory.getSymbolFactory().createSymbolofClass("F"));
		
		SymbolFactory.getSymbolFactory().registerSymbolClass("F", "F(x*p,2)", new Method(){
			public boolean calculate(ArrayList<Symbol> symbolSequence,
					int symbolIndex, Symbol calculatedSymbol) {
				float x = calculatedSymbol.getParameter("distance");
				calculatedSymbol.setParameter("distance", x*p);
				calculatedSymbol.setParameter("t", 2f);
				return true;
			}			
		});
		
		SymbolFactory.getSymbolFactory().registerSymbolClass("F", "F(x*h,1)", new Method(){
			public boolean calculate(ArrayList<Symbol> symbolSequence,
					int symbolIndex, Symbol calculatedSymbol) {
				float x = calculatedSymbol.getParameter("distance");
				calculatedSymbol.setParameter("distance", x*h);
				calculatedSymbol.setParameter("t", 1f);
				return true;
			}			
		});
		
		SymbolFactory.getSymbolFactory().registerSymbolClass("F", "F(x*q,0)", new Method(){
			public boolean calculate(ArrayList<Symbol> symbolSequence,
					int symbolIndex, Symbol calculatedSymbol) {
				float x = calculatedSymbol.getParameter("distance");
				calculatedSymbol.setParameter("distance", x*q);
				calculatedSymbol.setParameter("t", 0);
				return true;
			}			
		});
		
		Production p1 = SimpleParser.parseProduction("F->F(x*p,2)+F(x*h,1)--F(x*h,1)+F(x*q,0)");
		p1.setCondition(new Condition(){

			public boolean check(ArrayList<Symbol> symbolSequence,
					int symbolIndex) {
				Symbol symbol = symbolSequence.get(symbolIndex);				
				return symbol.getParameter("t")==0;
			}
			
		});
		
		SymbolFactory.getSymbolFactory().registerSymbolClass("F", "F(x,t-1)", new Method(){
			public boolean calculate(ArrayList<Symbol> symbolSequence,
					int symbolIndex, Symbol calculatedSymbol) {				
				calculatedSymbol.setParameter("t", calculatedSymbol.getParameter("t")-1);
				return true;
			}			
		});
		
		Production p2 = SimpleParser.parseProduction("F->F(x,t-1)");
		p2.setCondition(new Condition(){

			public boolean check(ArrayList<Symbol> symbolSequence,
					int symbolIndex) {
				Symbol symbol = symbolSequence.get(symbolIndex);					
				return symbol.getParameter("t")>0;
			}
			
		});
		
		addProduction(p1);
		addProduction(p2);
		
	}
	
	public void setRequiredParameters(){
		setRequiredParameter("turnAngle", 87f);
		setRequiredParameter("distance", 5f);
		setRequiredParameter("t", 0f);
	}

}
